package simpledb.util;

import simpledb.storage.Tuple;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * 页面缓存池，用于管理和迭代数据库页面的元组集合
 * 支持基于缓存率的页面迭代器缓存，实现跨页面元组的顺序访问
 * 核心机制：
 *   - 维护多个页面的元组迭代器列表
 *   - 通过 currentIterator 指针顺序访问各页面数据
 *   - 支持动态切换页面迭代器，提供统一的迭代接口
 */
public class PageCachePool {

    // 存储页面迭代器的列表，每个迭代器对应一个页面的元素集合
    private final List<Iterator<Tuple>> pageCache;

    // 当前正在使用的页面迭代器，指向 pageCache 中的某个元素
    private Iterator<Tuple>             currentIterator;

    // 当前迭代器在 pageCache 中的索引位置
    private int                         currentIndex;

    // 缓存池的最大容量，基于缓存率和总页面数计算得出
    private int                         maxCacheNum;

    /**
     * 初始化页面缓存池
     * @param cacheRate 缓存率（0~1之间的小数，表示缓存页面的比例）
     * @param totalPage 总页面数
     * @throws IllegalArgumentException 若 totalPage 为负数
     */
    public PageCachePool(final double cacheRate, final int totalPage) {
        this.maxCacheNum = (int) cacheRate * totalPage;
        if (this.maxCacheNum < 1) {
            this.maxCacheNum = 1;
        }
        this.pageCache = new ArrayList<>();
    }

    /**
     * 将一个页面的元组迭代器添加到缓存池中。如果当前缓存池未满，则将给定的迭代器添加到 pageCache 列表中
     * @param tupleIterator
     */
    public void addPage(final Iterator<Tuple> tupleIterator) {
        if (this.pageCache.size() < this.maxCacheNum) {
            this.pageCache.add(tupleIterator);
        }
    }

    /**
     * 初始化缓存池，设置为第一个页面的迭代器。
     * 重置当前索引为 0，并将 currentIterator 设置为缓存池中的第一个迭代器（如果有）。
     */
    public void init() {
        this.currentIndex = 0;
        if (this.pageCache.size() > 0) {
            this.currentIterator = this.pageCache.get(0);
        }
    }

    /**
     * 清空缓存池并释放资源。
     * 清除 pageCache 中的所有迭代器，并将 currentIterator 置为 null。
     */
    public void clear() {
        this.pageCache.clear();
        this.currentIterator = null;
    }

    /**
     * 返回缓存池的最大容量。
     * @return
     */
    public int getMaxCacheNum() {
        return maxCacheNum;
    }

    /**
     * 判断缓存池中是否还有更多元组可迭代
     * 1、如果 currentIterator 或 pageCache 为空，则返回 false
     * 2、检查当前迭代器是否有下一个元素，若有则返回 true
     * 3、如果当前迭代器没有更多元素且缓存池中有更多的迭代器，则切换到下一个迭代器并检查其是否有更多元素
     * 4、若所有迭代器均无更多元素，则返回 false
     * @return
     */
    public boolean hasNext() {
        if (this.currentIterator == null || this.pageCache.size() == 0) {
            return false;
        }
        if (this.currentIterator.hasNext()) {
            return true;
        }
        if (this.currentIndex + 1 < this.pageCache.size()) {
            this.currentIndex++;
            this.currentIterator = this.pageCache.get(this.currentIndex);
            return this.currentIterator.hasNext();
        }
        return false;
    }

    /**
     * 返回下一个元组
     * 调用 hasNext() 检查是否存在更多元素，若存在则返回当前迭代器的下一个元素；否则返回 null
     * @return
     */
    public Tuple next() {
        if (hasNext()) {
            return this.currentIterator.next();
        }
        return null;
    }
}
